<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2024/4/2
 * Time: 11:51
 */

namespace plugin\admin\app\logic\login;


use app\common\lib\Common;
use app\common\lib\JwtToken;
use plugin\admin\app\common\Util;
use plugin\admin\app\exception\AdminException;
use plugin\admin\app\logic\BaseLogic;
use plugin\admin\app\model\admin\Admin;
use plugin\admin\app\model\admin\LoginRecord;
use support\exception\BusinessException;
use support\Request;
use support\Response;

class LoginLogic extends BaseLogic
{
    protected static $instance;

    public function __construct()
    {

    }

    public static function getInstance()
    {
        //        if(is_object(self::$instance)){
//            return self::$instance;
//        }

        return new self();
    }

    public function login(Request $request):Response
    {
        $this->checkDatabaseAvailable();
        $captcha = $request->post('captcha', '');

        if (strtolower($captcha) !== session('captcha-login')) {
            throw new AdminException(4020,'验证码错误');
        }

        $username = $request->post('username', '');
        $password = $request->post('password', '');
        if (!$username) {
            throw new AdminException(4020,'用户名不能为空');
        }
        $this->checkLoginLimit($username);
        $admin = Admin::where(['username'=>$username,'isdel'=>0])->first();
        if (!$admin || !Util::passwordVerify($password, $admin->password)) {
            throw new AdminException(4020,'账户不存在或密码错误');
        }
        if ($admin->status != 1) {
            throw new AdminException(4020,'当前账户暂时无法登录');
        }
        $admin->login_at = date('Y-m-d H:i:s');
        $admin->save();
        $this->removeLoginLimit($username);
        $admin = $admin->toArray();

        $admin['login_time'] = time();
        $expireTime = 7*86400;
        $admin['expire_time'] = time() + $expireTime;
        $admin['token'] = JwtToken::getInstance()->createToken($admin, $expireTime);

        LoginRecord::getInstance()->insertData($admin['id'],$username,$admin['token']);
        $request->session()->forget('captcha-login');

        return $this->json(0, 'ok', $admin);
    }

    /**
     * 检查登录频率限制
     * @param $username
     * @throws AdminException
     */
    protected function checkLoginLimit($username)
    {
        $limit_log_path = runtime_path() . '/login';
        if (!is_dir($limit_log_path)) {
            Common::mkdirs($limit_log_path);
        }
        $limit_file = $limit_log_path . '/' . md5($username) . '.limit';
        $time = date('YmdH') . ceil(date('i')/5);
        $limit_info = [];
        if (is_file($limit_file)) {
            $json_str = file_get_contents($limit_file);
            $limit_info = json_decode($json_str, true);
        }

        if (!$limit_info || $limit_info['time'] != $time) {
            $limit_info = [
                'username' => $username,
                'count' => 0,
                'time' => $time
            ];
        }
        $limit_info['count']++;
        file_put_contents($limit_file, json_encode($limit_info));
        if ($limit_info['count'] >= 5) {
            throw new AdminException(4020,'登录失败次数过多，请5分钟后再试');
        }
    }

    /**
     * 解除登录频率限制
     * @param $username
     * @return void
     */
    protected function removeLoginLimit($username)
    {
        $limit_log_path = runtime_path() . '/login';
        $limit_file = $limit_log_path . '/' . md5($username) . '.limit';
        if (is_file($limit_file)) {
            unlink($limit_file);
        }
    }
}